package com.zy.explore.db.infrastructure.plugins.multidbsupport.sqlchange;

import com.zy.explore.db.infrastructure.plugins.multidbsupport.sqlchange.base.SqlOper;
import com.zy.explore.db.infrastructure.plugins.multidbsupport.sqlchange.function.AbstractFunChangeFactory;
import com.zy.explore.db.infrastructure.plugins.multidbsupport.sqlchange.function.MysqlToOracleFunChangeFactory;
import com.zy.explore.db.infrastructure.plugins.multidbsupport.sqlchange.function.SqlFunctionUtils;
import com.zy.explore.db.infrastructure.plugins.multidbsupport.sqlchange.limit.SqlLimitUtils;
import com.zy.explore.db.infrastructure.plugins.multidbsupport.sqlchange.select.SqlSelectUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
 * 建类说明：sql改变
 *
 * @author 中国印
 * @date 2022年02月16日 23:16:15
 */
@SuppressWarnings("unchecked")
public class Sqlchange {

    public static String process(String sql) {
        AbstractFunChangeFactory changeFactory = new MysqlToOracleFunChangeFactory();
        List<SqlOper> sqlOperList1 = SqlFunctionUtils.find(sql, changeFactory);
        List<SqlOper> sqlOperList2 = SqlLimitUtils.find(sql);
        List<SqlOper> sqlOperList3 = SqlSelectUtils.find(sql);

        List<SqlOper> mergeList = mergeList(sqlOperList1, sqlOperList2, sqlOperList3);
        return change(sql, mergeList);
    }

    /**
     * 合并list
     */
    public static <T> List<T> mergeList(List<T>... lists) {

        List<T> mergeList = new ArrayList<>();
        for (List<T> list : lists) {
            if (list == null) {
                continue;
            }
            mergeList.addAll(list);
        }

        return mergeList;
    }

    public static String change(String sql, List<SqlOper> sqlOperList) {
        if (sqlOperList == null || sqlOperList.isEmpty()) {
            return sql;
        }
        Collections.sort(sqlOperList);

        StringBuilder sb = new StringBuilder();
        int pre = 0;

        for (SqlOper oper : sqlOperList) {
            int starIdx = oper.getStarIdx();
            if (pre < starIdx) {
                sb.append(sql, pre, starIdx);
                pre = starIdx;
            }

            if (oper.getOper() == SqlOper.OPER_ADD) {
                sb.append(oper.getStr());
            } else if (oper.getOper() == SqlOper.OPER_DELETE) {
                pre = oper.getEndIdx();
            } else if (oper.getOper() == SqlOper.OPER_REPLACE) {
                sb.append(oper.getStr());
                pre = oper.getEndIdx();
            }
        }

        if (pre < sql.length()) {
            sb.append(sql.substring(pre));
        }

        return sb.toString();

    }


}
